package com.iqik.sc.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Component
public class IpInbreakFilter implements GlobalFilter, Ordered, Runnable {

    private static Map<String, Map<String, Long>> IP_REMARK = new ConcurrentHashMap<>();

    private static Map<String, Long> BLACK_LIST_IP = new ConcurrentHashMap<>();

    public IpInbreakFilter() {
        Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(this, 300, 60, TimeUnit.SECONDS);
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String clientIp = request.getRemoteAddress().getHostString();
        System.out.println("====================>" + clientIp);
        if (BLACK_LIST_IP.keySet().contains(clientIp)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED); // 设置状态码
            String data = "Request be denied";
            response.bufferFactory().wrap(data.getBytes());
            return response.writeWith(Mono.just(response.bufferFactory().wrap(data.getBytes())));
        }
        Map<String, Long> remark = IP_REMARK.get(clientIp);
        if (remark == null || remark.isEmpty()) {
            remark = new ConcurrentHashMap<>();
            remark.put("times", 1L);
            remark.put("exp", Calendar.getInstance().getTimeInMillis() + 60 * 1000);
        } else {
            remark.put("times", remark.get("times") + 1L);
            if (Calendar.getInstance().getTimeInMillis() <= remark.get("exp")
                    && remark.get("times").intValue() >= 100) {
                BLACK_LIST_IP.put(clientIp, Calendar.getInstance().getTimeInMillis());
                response.setStatusCode(HttpStatus.UNAUTHORIZED); // 设置状态码
                String data = "Request be denied";
                response.bufferFactory().wrap(data.getBytes());
                return response.writeWith(Mono.just(response.bufferFactory().wrap(data.getBytes())));
            }
        }
        IP_REMARK.put(clientIp, remark);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void run() {
        for (Map.Entry<String, Long> entry : BLACK_LIST_IP.entrySet()) {
            if (entry.getValue() + 5 * 60 * 1000 >= Calendar.getInstance().getTimeInMillis()) {
                BLACK_LIST_IP.remove(entry.getKey());
            }
        }
    }
}
